/*
 *  SerialIOProcess.java
 *
 *  copyright (c) 2006, tom dinchak & lorenzo orselli
 * 
 *  this file is part of jserialio.
 *
 *  jserialio is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  jserialio is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *  You should have received a copy of the GNU General Public License
 *  along with jserialio; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *
 *  created on August 3, 2006, 11:43 AM
 *
 */

package serialio;

import java.util.StringTokenizer;
import java.io.*;

import gnu.io.*;

import com.illposed.osc.*;
import java.util.Properties;
import java.io.FileInputStream;

/**
 *
 * @author tom
 */
public class SerialIOProcess {
    
    OSCReceiver oscr = null;
    RS232Receiver rs232r = null;

    InputStream serialin;
	OutputStream serialout;

    String SerialPortStr = "COM2";
    String OSCInPortStr = "8080";
    String OSCOutPortStr = "8000";
    String BaudRateStr = "9600";
    static String CableOrientation = "L";
    public boolean senderror = false;
    
    CommPortOwnershipListener portListener;
    
    OSCHandler oschandler = null;
    RS232Handler rs232handler = null;
    
    public void process(String str) {
        OSCMessage msg = new OSCMessage();

        if (str == null) {
            System.out.println("Exiting SerialIO...");
            try {
                Thread.sleep(100);
            } catch (Exception e) {
                // do nothing
            }
            try {
            	rs232r.stopReceiver();
            	oscr.stopReceiver();
            } catch (Exception e) {
            	e.printStackTrace();
            }
            System.exit(1);
        } 

        if (str.equals("")) {
            System.out.println("no input");
        }

        
        StringTokenizer st = new StringTokenizer(str);
        String command = st.nextToken();
        
        if (command.startsWith("/box")) {
            while (st.hasMoreTokens()) {
                msg.addArgument(new Integer(st.nextToken()));
            }
        }
        
        if (command.equals("help")) {
            System.out.println("--- Configuration");
            System.out.println("oscinport <port number>  - Sets the OSC port to listen on (default: 8080)");
            System.out.println("oscoutport <port number> - Sets the OSC port to send to (default: 8000)");
            System.out.println("serialport <identifier>  - Sets the COM port of the monome (default: COM3)");
            System.out.println("baudrate <speed>  - Sets the baud rate of the serial port (default: 9600)");
            System.out.println("status - Displays the status of SerialIO and the monome");
            System.out.println("quit - Exits the program");
            System.out.println("help - Displays this text");
            System.out.println("--- OSC Messages");
            System.out.println("/box/led <x [0-7]> <y [0-7]> <state [0-1]>");
            System.out.println("/box/led_col <col [0-7]> <state [0-255]>");
            System.out.println("/box/led_row <row [0-7]> <state [0-255]>");
            System.out.println("/box/intensity <intensity [0-15]>");
            System.out.println("/box/test <state [0-1]>");
            System.out.println("/box/adc_enable <adc [0-4]> <enabled [0-1]>");
            System.out.println("/box/shutdown <state [0-1]>");
        } else if (command.equals("status")) {
            System.out.println("OSC Input Port: " + OSCInPortStr);
            System.out.println("OSC Output Port: " + OSCOutPortStr);
            System.out.println("Serial Port: " + SerialPortStr);
            System.out.println("Baud Rate: " + BaudRateStr);
            System.out.println("Cable Orientation: "+ CableOrientation);
            System.out.println("OSCReceiver: "+oscr.getStatus());
            System.out.println("RS232Receiver: "+rs232r.getStatus());
        } else if (command.equals("oscinport")) {
            this.OSCInPortStr = st.nextToken();
            System.out.println("Stopping OSCReceiver...");
            try {
            	oscr.stopReceiver();
            } catch (Exception e) {
            	e.printStackTrace();
            }
            try {
                Thread.sleep(100);
            } catch (Exception e) {
                e.printStackTrace();
            }
            oscr = new OSCReceiver(serialout, this.OSCInPortStr, this);
            oscr.start();
        } else if (command.equals("oscoutport")) {
            this.OSCOutPortStr = st.nextToken();
            System.out.println("Stopping RS232Receiver...");
            try {
            	rs232r.stopReceiver();
            } catch (Exception e) {
            	e.printStackTrace();
            }
            try {
                Thread.sleep(100);
            } catch (Exception e) {
                e.printStackTrace();
            }
            rs232r = new RS232Receiver(this.OSCOutPortStr, this, portListener);
            rs232r.start();
        } else if (command.equals("serialport")) {
            System.out.println("Stopping RS232Receiver...");
            System.out.println("Stopping OSCReceiver...");
            try {
            	rs232r.stopReceiver();
            	oscr.stopReceiver();
            } catch (Exception e) {
            	e.printStackTrace();
            }
            SerialPortStr = st.nextToken();
            try {
                Thread.sleep(100);
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("Setting Serial Port to "+SerialPortStr+", "+BaudRateStr+"bps");
            setSerialPort(SerialPortStr, BaudRateStr);
        } else if (command.equals("baudrate")) {
            System.out.println("Stopping RS232Receiver...");
            System.out.println("Stopping OSCReceiver...");
            try {
            	rs232r.stopReceiver();
            	oscr.stopReceiver();
            } catch (Exception e) {
            	e.printStackTrace();
            }
            BaudRateStr = st.nextToken();
            try {
                Thread.sleep(100);
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("Setting Serial Port to "+SerialPortStr+", "+BaudRateStr+"bps");
            setSerialPort(SerialPortStr, BaudRateStr);
        } else if (command.equals("quit")) {
            System.out.println("Exiting SerialIO...");
            try {
                Thread.sleep(100);
            } catch (Exception e) {
                // do nothing
            }
            try {
            	rs232r.stopReceiver();
            	oscr.stopReceiver();
            } catch (Exception e) {
            	e.printStackTrace();
            }
            System.exit(1);
        } else if (command.equals("/box/led")) {
            oscr.ledlistener.acceptMessage(null, msg);
        } else if (command.equals("/box/led_row")) {
            oscr.ledrowlistener.acceptMessage(null, msg);
        } else if (command.equals("/box/led_col")) {
            oscr.ledcollistener.acceptMessage(null, msg);
        } else if (command.equals("/box/intensity")) {
            oscr.intensitylistener.acceptMessage(null, msg);
        } else if (command.equals("/box/test")) {
            oscr.testlistener.acceptMessage(null, msg);
        } else if (command.equals("/box/adc_enable")) {
            oscr.adcenablelistener.acceptMessage(null, msg);
        } else if (command.equals("/box/shutdown")) {
            oscr.shutdownlistener.acceptMessage(null, msg);
        } else if (command.equals("/box/reset")) {
        	oscr.resetlistener.acceptMessage(null, msg);
        } else {          
            System.out.println("Command not found.  Type 'help' for a list of commands.");
        }
        System.out.println("");
    }
    
    public void setSerialPort(String identifier, String baudrate) {
        try {        
                if (oscr != null) {
                    try {
                    	oscr.stopReceiver();
                    } catch (Exception e) {
                    	e.printStackTrace();
                    }
                }
                
                if (rs232r != null) {
                    try {
                    	rs232r.stopReceiver();
                    } catch (Exception e) {
                    	e.printStackTrace();
                    }
                }
                
                Thread.sleep(1000);

                rs232r = new RS232Receiver(OSCOutPortStr, this, portListener);
                SerialPortResponse response = rs232r.setSerialPort(SerialPortStr, BaudRateStr);
                serialin = response.getSerialin();
                serialout = response.getSerialout();
                if (serialout != null) {
                	oscr = new OSCReceiver(serialout, OSCInPortStr, this);
                }
                oscr.setUncaughtExceptionHandler(oschandler);
                oscr.start();
                rs232r.setUncaughtExceptionHandler(rs232handler);
                rs232r.start();
                
            } catch (Throwable e) {
                e.printStackTrace();
            }
            
    }
    
    public SerialIOProcess() {
        try {
            FileInputStream fin = new FileInputStream(new File("serialio.conf"));
            Properties props = new Properties();
            props.load(fin);
     
            SerialPortStr = props.getProperty("serialport");
            BaudRateStr = props.getProperty("baudrate");
            OSCInPortStr = props.getProperty("oscinport");
            OSCOutPortStr = props.getProperty("oscoutport");
            CableOrientation = props.getProperty("cableorientation");

            oschandler = new OSCHandler(this);
            rs232handler = new RS232Handler(this);
            
            portListener = new SerialPortListener(SerialPortStr, BaudRateStr, this);
            
            setSerialPort(SerialPortStr, BaudRateStr);
            BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
            String str = "";
            Thread.sleep(100);
            process("/box/reset");
            System.out.println("");
            System.out.println("Welcome to SerialIO.  Type 'help' for a list of commands.");
            while (str != null) {
                Thread.sleep(100);
                System.out.print("SerialIO> ");
                str = in.readLine();
                if (!str.equals("")) {
                    process(str);
                }
            }
        } catch (Exception e) {
        	e.printStackTrace();
        }
        
    }

    public void RestartOSCReceiver() {
    	System.out.println("Called restart osc");
    }
    
    public void RestartRS232Receiver() {
        setSerialPort(SerialPortStr, BaudRateStr);
    }
    
}
